package com.tg.service.flow.flow;

import com.alibaba.fastjson.JSONObject;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FlowEngine<Node extends  FlowNode> implements IFlowEngine {

    private Integer level = 0;

    private Integer maxLevel = 20;

    private List<Node> nodes;

    private Map<String, Node> nodeMap;

    public FlowEngine(List<Node> nodes) {
        this.nodes = nodes;
        this.nodeMap = nodes.stream().collect(
                Collectors.toMap(Node::getId, Function.identity(), (k1, k2) -> k1)
        );
    }

    public void run(JSONObject req) {
        Node first = this.findFirst();

        Tuple tuple = new Tuple();
        tuple.setReq(req);

        this.invokeRule(first, tuple);
    }

    protected Node findFirst() {
        return this.nodes.stream().filter(Node::isBeFirst).findFirst().orElse(null);
    }

    private void invokeRule(Node node, Tuple tuple) {
        this.level += 1;

        if (level > maxLevel) {
            return;
        }

        boolean result = this.validateNode(node.getKey(), tuple);
        if (!result) {
            return;
        }

        List<String> nextIds = node.getNextIds();
        if (Objects.isNull(nextIds) || nextIds.isEmpty()) {
            return;
        }

        for (String nextId : nextIds) {
            Node nextNode = this.nodeMap.get(nextId);
            boolean pass = this.validateCondition(nextNode.getCondition(), tuple);
            if (pass) {
                this.invokeRule(nextNode, tuple);
                break;
            }
        }
    }

}
